/*
 * @(#)ShellLS.java	1.0 Apr 18, 2008
 *
 *	The MIT License
 *
 *	Copyright (c) 2008 Malachi de AElfweald <malachid@gmail.com>
 *
 *	Permission is hereby granted, free of charge, to any person obtaining a copy
 *	of this software and associated documentation files (the "Software"), to deal
 *	in the Software without restriction, including without limitation the rights
 *	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *	copies of the Software, and to permit persons to whom the Software is
 *	furnished to do so, subject to the following conditions:
 *
 *	The above copyright notice and this permission notice shall be included in
 *	all copies or substantial portions of the Software.
 *
 *	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *	THE SOFTWARE.
 */
package org.eoti.io.console.shell.cmd;

import org.eoti.io.console.shell.ShellException;
import org.eoti.io.console.shell.ShellFileExtension;
import org.eoti.io.file.filter.DirectoryFileFilter;
import org.eoti.util.size.Bytes;

import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Date;
import java.util.List;

public class ShellLS
	extends ShellFileExtension
{
	protected DirectoryFileFilter dirFilter = new DirectoryFileFilter();
	protected int longestName = 1;

	public ShellLS()
	{
		super();
	}

	protected void computeFormat()
	{
		int byteSize = Bytes.B.convertFrom(BigInteger.ONE, Bytes.TB).toString().length();
		int dateSize = sdf.format(new Date()).length();
		int remaining = getConsoleWidth() - byteSize - dateSize - 9 /* spaces */ - 5 /* permissions */;
		int nameSize = Math.min(remaining, longestName);
		remaining -= nameSize;
		if(remaining <= 0)
		{
			nameSize -= remaining;
			nameSize++;
			remaining = 1;
		}
		
		// [sp][sp][permissions][sp][filename][sp][sp][sp][sp][size][sp][sp][date]
		setFormat(
				"  " +
				defaultFormat(1) + // hidden
				defaultFormat(1) + // directory
				defaultFormat(1) + // read
				defaultFormat(1) + // write
				defaultFormat(1) + // execute
				" " +
				defaultFormat(nameSize) + // filename
				"    " +
				defaultFormat(byteSize) + // length
				"  " +
				defaultFormat(dateSize) + // modified
				defaultFormat(remaining) + // extra spaces
				"\n"
		);
	}

	public void execute(List<String> arguments)
			throws ShellException
	{
		if(arguments.size() > 1)
			error("Too many parameters.");

		File dir = shell.getCurrentDirectory();
		if(arguments.size() == 1)
			dir = new File(arguments.get(0)).getAbsoluteFile();

		if(dir == null)
			error("Unknown directory.");

		try{
			shell.format("Listing of '%s'\n", dir.getCanonicalPath());
		} catch(IOException e){
			shell.format("Listing of '%s'\n", dir.getAbsolutePath());
		}

		longestName = 0;
		File[] files = dir.listFiles();
		for(File file : files)
			longestName = Math.max(longestName, file.getName().length());

		computeFormat();

		for(File file : files)
		{
			format(
				(file.isHidden()?"h":"-"),
				(file.isDirectory()?"d":"-"),
				(file.canRead()?"r":"-"),
				(file.canWrite()?"w":"-"),
				(file.canExecute()?"x":"-"),
				file.getName(),
				size(file),
				date(file),
				" "
			);
		}
		
		int dirs = dir.listFiles(dirFilter).length;
		shell.format("\t%d files and %d directories\n", files.length - dirs, dirs);
		shell.println();
	}

	public String getName()
	{
		return "ls";
	}

	public String getUsage()
	{
		return "'ls' list files in the current directory\n'ls directory' list files in the specified directory";
	}
}
